package lib.bone.audit.workload.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Validator;
import com.alibaba.fastjson.JSONObject;
import lib.bone.access.config.cycle.NepuCycle;
import lib.bone.access.config.cycle.NepuCycleDAO;
import lib.bone.access.config.cycle.NepuCycleService;
import lib.bone.access.constant.*;
import lib.bone.access.module.dict.DictServiceCtl;
import lib.bone.access.module.dict.dao.NepuAwardDictDAO;
import lib.bone.access.module.dict.entity.NepuAwardDict;
import lib.bone.access.module.dict.entity.NepuTopicDict;
import lib.bone.access.module.post.NepuPostServiceImpl;
import lib.bone.access.module.post.domain.NepuPost;
import lib.bone.audit.domain.vo.FlowWorkLinkVO;
import lib.bone.audit.workload.attach.ResearchAttach;
import lib.bone.audit.workload.dao.NepuWorkloadDAO;
import lib.bone.audit.workload.domain.NepuWorkload;
import lib.bone.audit.workload.domain.WorkloadUseLog;
import lib.bone.audit.workload.domain.dto.AnalysisUserWorkloadDTO;
import lib.bone.audit.workload.domain.dto.DistributeDTO;
import lib.bone.audit.workload.domain.dto.DistributeItem;
import lib.bone.audit.workload.domain.dto.WorkloadCountVO;
import lib.bone.audit.workload.domain.vo.*;
import lib.bone.audit.workload.service.NepuWorkloadService;
import lib.bone.audit.workload.service.WorkloadUseLogService;
import lib.bone.common.constant.ResponseCodeConst;
import lib.bone.common.core.domain.PageResultDTO;
import lib.bone.common.core.domain.ResponseDTO;
import lib.bone.common.exception.BusinessException;
import lib.bone.common.utils.JsonUtil;
import lib.bone.flow.constant.FlowWorkStatusConst;
import lib.bone.flow.domain.entity.FlowWork;
import lib.bone.flow.service.FlowTaskService;
import lib.bone.flow.service.FlowWorkService;
import lib.bone.nepudata.dao.NepuAwardDAO;
import lib.bone.nepudata.domain.entity.NepuAward;
import lib.bone.nepudata.domain.entity.NepuTopic;
import lib.bone.nepudata.service.ResearchServiceCtl;
import lib.bone.nepudata.service.impl.NepuTopicServiceImpl;
import lib.bone.system.domain.entity.SysDept;
import lib.bone.system.domain.entity.SysUser;
import lib.bone.system.domain.vo.UserBaseVO;
import lib.bone.system.service.SysDeptService;
import lib.bone.system.service.SysUserRoleService;
import lib.bone.system.service.SysUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;

import javax.transaction.Transactional;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.Future;
import java.util.stream.Collectors;

/**
 * @author kindear
 */
@Slf4j
@Service
public class NepuWorkloadServiceImpl implements NepuWorkloadService {

    @Autowired
    NepuWorkloadDAO nepuWorkloadDAO;

    @Autowired
    WorkloadUseLogService logService;

    @Autowired
    SysUserRoleService sysUserRoleService;

    @Autowired
    ResearchServiceCtl researchServiceCtl;

    @Autowired
    FlowTaskService flowTaskService;

    @Autowired
    NepuAwardDAO nepuAwardDAO;

    @Autowired
    NepuTopicServiceImpl nepuTopicService;

    @Autowired
    NepuAwardDictDAO nepuAwardDictDAO;

    @Autowired
    NepuCycleDAO nepuCycleDAO;

    @Autowired
    DictServiceCtl dictServiceCtl;

    @Autowired
    NepuCycleService nepuCycleService;

    @Autowired
    NepuPostServiceImpl nepuPostService;

    @Autowired
    SysUserService userService;

    @Autowired
    FlowWorkService flowWorkService;

    @Autowired
    SysDeptService sysDeptService;

    @Override
    public List<NepuWorkload> getByLinkIds(List<String> linkIds) {
        return nepuWorkloadDAO.findByLinkIdIn(linkIds);
    }

    @Override
    public List<NepuWorkload> getNowWorkload(String userId, List<String> subIds) {
        return nepuWorkloadDAO.findByUserIdAndCycleIdIn(userId,subIds);
    }

    /**
     * 修复工作量记录
     */
    @Async("threadExecutor")
    @Transactional
    public void fixWorkload(NepuWorkload nepuWorkload){
        if (nepuWorkload.getWorkloadLock().equals(1)){
            log.info("该纵向课题已被分配:"+nepuWorkload.getLinkId());
            return;
        }
        if (Validator.isEmpty(nepuWorkload.getLinkId())){
            log.info("LinkId为空:"+nepuWorkload.getId());
            return;
        }
        Optional<NepuTopic> nepuTopicOp = nepuTopicService.getById(nepuWorkload.getLinkId());
        NepuTopic topic = new NepuTopic();
        if (!nepuTopicOp.isPresent()){
            log.info("nepuTopicOp不存在："+nepuWorkload.getLinkId());
            return;
        }
        BeanUtil.copyProperties(nepuTopicOp.get(),topic,CopyOptions.create().setIgnoreError(true).setIgnoreNullValue(true));
        String cycleId = nepuCycleService.getNowResearchCycleId();
        Optional<NepuCycle> nepuCycleOp = nepuCycleService.getById(cycleId);
        NepuCycle nepuCycle = new NepuCycle();
        if (Validator.isNotEmpty(nepuCycleOp)){
            BeanUtil.copyProperties(nepuCycleOp.get(),nepuCycle, CopyOptions.create().setIgnoreNullValue(true).setIgnoreError(true));
        }
        // 获取开始时间和结束时间
        Date startDate;
        Date endDate;
        if (topic.getStartDate().compareTo(nepuCycle.getStartDate())==-1||
                topic.getStartDate().compareTo(nepuCycle.getStartDate())==0){
            startDate = nepuCycle.getStartDate();
        }else{
            startDate = topic.getStartDate();

        }
        if (topic.getEndDate().compareTo(nepuCycle.getEndDate())==-1||
                topic.getStartDate().compareTo(nepuCycle.getStartDate())==0){
            endDate = topic.getEndDate();
        }else{
            endDate = nepuCycle.getEndDate();
        }
        // 2022-5-30 bug fix 工作量计算
        long betweenMonth = DateUtil.betweenMonth(startDate,endDate,false) + 1;
        // 获取词典信息
        Optional<Object> dictOp = dictServiceCtl.getById(topic.getTopicDictId(),ResearchTypeConst.TOPIC);
        if (!dictOp.isPresent()) {
            log.info("[{}]:工作量修复失败",topic.getTopicName());
            return;
        }
        NepuTopicDict dict = (NepuTopicDict) dictOp.get();
        double workload = dict.getWorkloadMax() * betweenMonth * 1.0 / 12;
        double oldLog = nepuWorkload.getWorkload();
        // 更新对应记录
        nepuWorkload.setWorkload(workload);
        this.updateOne(nepuWorkload);
//        Optional<NepuWorkload> workloadOp = workloadService.getLinkEntity(topic.getId());
//        if (!workloadOp.isPresent()) throw new BusinessException(ResponseCodeConst.NOT_FOUND);
//        NepuWorkload workload1 = workloadOp.get();

//        workload1.setWorkload(workload);
        if (workload!=oldLog){
        log.info("[{}]:原工作量:{},经修正后:{}",topic.getTopicName(),oldLog,workload);
        }
    }

    @Override
    public List<NepuWorkload> getByIds(List<String> ids) {
        return nepuWorkloadDAO.findByIdIn(ids);
    }

    @Override
    @Transactional
    public void batchSave(List<NepuWorkload> workloads) {
        nepuWorkloadDAO.saveAll(workloads);
    }

    @Override
    public double convertSalary(Example<NepuWorkload> example, String useMethod) {
        List<NepuWorkload> list = finAll(example);
        // 根据 工作量锁 排除无法进行转化的记录
        list = list.stream().filter(ele->{
            return ele.getWorkloadLock() > 0 && ele.getUsedUp().equals(0);
        }).collect(Collectors.toList());

        // 构建日志
        List<WorkloadUseLog> useLogs = new ArrayList<>();

        // 转化统计
        double leftSum = 0.0;

        for (NepuWorkload ele:list){

            // 计算剩余工作量
            Double leftWorkload = ele.getWorkload() - ele.getUsedWorkload();

            leftSum = leftSum + leftWorkload;

            WorkloadUseLog useLog = buildLog(ele, leftWorkload,useMethod);
            // buildResearchUseLog(ele.getCycleId(), ele.getUserId(), needWorkload - workloadSum, ele.getId(), UseMethodConst.DEDUCT_RESEARCH, ele.getLinkId(), attach.getResearchName(), ele.getCreatedTime());
            useLogs.add(useLog);
            ele.setUsedWorkload(ele.getWorkload());
            ele.setUsedUp(1);
            updateOne(ele);

        }

        // 写入日志记录
        logService.saveList(useLogs);
        // 返回转化总量
        return leftSum;

    }

    @Override
    public double convertSalary(List<NepuWorkload> list, String useMethod) {
        // 根据 工作量锁 排除无法进行转化的记录
        list = list.stream().filter(ele->{
            return ele.getWorkloadLock() > 0 && ele.getUsedUp().equals(0);
        }).collect(Collectors.toList());

        // 构建日志
        List<WorkloadUseLog> useLogs = new ArrayList<>();

        // 转化统计
        double leftSum = 0.0;

        for (NepuWorkload ele:list){

            // 计算剩余工作量
            Double leftWorkload = ele.getWorkload() - ele.getUsedWorkload();

            leftSum = leftSum + leftWorkload;

            WorkloadUseLog useLog = buildLog(ele, leftWorkload,useMethod);
            // buildResearchUseLog(ele.getCycleId(), ele.getUserId(), needWorkload - workloadSum, ele.getId(), UseMethodConst.DEDUCT_RESEARCH, ele.getLinkId(), attach.getResearchName(), ele.getCreatedTime());
            useLogs.add(useLog);
            ele.setUsedWorkload(ele.getWorkload());
            ele.setUsedUp(1);
            updateOne(ele);

        }

        // 写入日志记录
        logService.saveList(useLogs);
        // 返回转化总量
        return leftSum;

    }

    @Override
    public double deduction(List<NepuWorkload> list, Double nw, String useMethod,String postType) {
        Double needWorkload = nw;
        //log.info("缺额：{}",needWorkload);
        // 所需值为 0
        if (needWorkload.equals(0.0)){
            return 0;
        }

        // 根据 工作量锁 排除无法进行抵扣的记录 -- 未用尽
        list = list.stream().filter(ele->{
            return ele.getWorkloadLock() > 0 && ele.getUsedUp().equals(0);
        }).collect(Collectors.toList());

        List<NepuWorkload> workloads = new ArrayList<>();

        if (PostTypeConst.TEACH.equals(postType)){
            // 教学岗位
            for (NepuWorkload nepuWorkload : list) {
                workloads.add(nepuWorkload);
            }

        }else if (PostTypeConst.SYNTHESIS.equals(postType)){
            // 教学 -  研究岗位
            for (NepuWorkload nepuWorkload : list) {
                if (nepuWorkload.getWorkloadType().equals(WorkloadTypeConst.RESEARCH)){
                    String level = nepuWorkload.getWorkloadLevel().substring(0,1);
                    if (level.equals("A")||level.equals("B")){
                        workloads.add(nepuWorkload);
                    }
                }else if (nepuWorkload.getWorkloadType().equals(WorkloadTypeConst.TEACH)||nepuWorkload.getWorkloadType().equals(WorkloadTypeConst.OTHER)){
                    workloads.add(nepuWorkload);
                }else if(nepuWorkload.getWorkloadType().equals(WorkloadTypeConst.MANAGE)){
                    workloads.add(nepuWorkload);
                }
            }
        }else if (PostTypeConst.RESEARCH.equals(postType)){
            // 研究型岗位
            for (NepuWorkload nepuWorkload : list) {
                if (nepuWorkload.getWorkloadType().equals(WorkloadTypeConst.RESEARCH)){
                    String level = nepuWorkload.getWorkloadLevel().substring(0,1);
                    if (level.equals("A")){
                        workloads.add(nepuWorkload);
                    }
                }else if (nepuWorkload.getWorkloadType().equals(WorkloadTypeConst.TEACH)||nepuWorkload.getWorkloadType().equals(WorkloadTypeConst.OTHER)){
                    workloads.add(nepuWorkload);
                }else if(nepuWorkload.getWorkloadType().equals(WorkloadTypeConst.MANAGE)){
                    workloads.add(nepuWorkload);
                }
            }
        }

        // 构建日志
        List<WorkloadUseLog> useLogs = new ArrayList<>();
        for (NepuWorkload ele:workloads){
            if (ele.getWorkload()-ele.getUsedWorkload() > needWorkload){
                WorkloadUseLog useLog = buildLog(ele,needWorkload ,useMethod);
                useLogs.add(useLog);
                ele.setUsedWorkload(ele.getUsedWorkload() + needWorkload);
                updateOne(ele);
                needWorkload = 0.0;
                break;
            }else {
                WorkloadUseLog useLog = buildLog(ele,ele.getWorkload()-ele.getUsedWorkload(),useMethod);
                useLogs.add(useLog);
                needWorkload -= (ele.getWorkload() - ele.getUsedWorkload());
                ele.setUsedWorkload(ele.getWorkload());
                ele.setUsedUp(1);
                updateOne(ele);

            }
        }
        // 写入日志记录
        logService.saveList(useLogs);
        // 返回缺额工作量
        return needWorkload;
    }

    @Override
    public double deduction(Example<NepuWorkload> example, Double needWorkload,String useMethod,String postType) {
        List<NepuWorkload> workloads = finAll(example);
        return deduction(workloads,needWorkload,useMethod,postType);
    }

    @Override
    public List<NepuWorkload> finAll(Example<NepuWorkload> example) {
        List<NepuWorkload> list =  nepuWorkloadDAO.findAll(example);
//        log.info(list.toString());
        list = list.stream().peek(ele->{
            if(Validator.isEmpty(ele.getWorkloadLevel())){
                ele.setWorkloadLevel("E1");
            }
        }).collect(Collectors.toList());
        return list.stream().sorted(Comparator.comparing(NepuWorkload::getWorkloadLevel).reversed()).collect(Collectors.toList());
    }

    @Async("threadExecutor")
    @Override
    public void buildAwardDictName(NepuWorkload workload) {
        String workloadAttach = workload.getWorkloadAttach();
        ResearchAttach attach = JsonUtil.string2Obj(workloadAttach,ResearchAttach.class);
        if (attach!=null&&attach.getResearchType().equals("教学科研获奖")){
            String id=attach.getResearchId();
            Optional<NepuAward> nepuAwardOp=nepuAwardDAO.findById(id);
            NepuAward nepuAward=nepuAwardOp.get();
            //没有唯一标识
            String dictId=nepuAward.getAwardDictId();
            Optional<NepuAwardDict> nepuAwardDictOp=nepuAwardDictDAO.findById(dictId);
            NepuAwardDict nepuAwardDict=nepuAwardDictOp.get();
            String dictName=nepuAwardDict.getAwardName();
            attach.setDictName(dictName);
            log.info("dictName:{}",dictName);
            workloadAttach=JsonUtil.obj2String(attach);
            workload.setWorkloadAttach(workloadAttach);
            nepuWorkloadDAO.save(workload);
        }

    }

    @Async("threadExecutor")
    @Override
    public void buildParentCycleId(NepuWorkload workload) {
        String cycleId = workload.getCycleId();
        Optional<NepuCycle> nepuCycleOp=nepuCycleDAO.findById(cycleId);
        NepuCycle nepuCycle=nepuCycleOp.get();
        String parentCycleId=nepuCycle.getParentId();
        if(parentCycleId==null){
            workload.setParentId(cycleId);
        }else {
            workload.setParentId(parentCycleId);
        }
        nepuWorkloadDAO.save(workload);
    }

    @Override
    public List<NepuWorkload> getAll() {
        return nepuWorkloadDAO.findAll();
    }


    @Override
    @Async("threadExecutor")
    public Future<FlowWorkLinkVO> checkFlowWorkWithWorkload(FlowWork flowWork) {
        // 构建返回信息
        FlowWorkLinkVO vo = new FlowWorkLinkVO();
        BeanUtil.copyProperties(flowWork,vo,CopyOptions.create().setIgnoreNullValue(true).setIgnoreError(true));
        vo.setFlowWorkId(flowWork.getId());
        // 获取关联实体ID
        String serviceId = flowWork.getServiceId();
        // 获取关联周期ID
        String cycleId = flowWork.getCycleId();
        // 构建Example
        NepuWorkload t = new NepuWorkload();
        // 传入 Example 特征
        t.setLinkId(serviceId);
        t.setCycleId(cycleId);
        // 类型为科研工作量
        t.setWorkloadType(WorkloadTypeConst.RESEARCH);
        // 为申请获得
        t.setWorkloadSource(WorkloadSourceConst.APPLY);
        // 构建查询
        Example<NepuWorkload> example = Example.of(t);

        List<NepuWorkload> workloads = nepuWorkloadDAO.findAll(example);

        if (workloads.size() != 1){
            if (flowWork.getFlowWorkStatus().equals(FlowWorkStatusConst.FINISHED)){
                log.info("ID:【{}】流程实例对应工作量数目存在问题",flowWork.getId());
            }
            else if (flowWork.getFlowWorkStatus().equals(FlowWorkStatusConst.IN_PROGRESS)){
                log.info("ID:【{}】流程实例暂未完成，无工作量写入",flowWork.getId());
            }else {
                log.info("ID:【{}】流程实例状态为【{}】,工作量记录为【{}】",flowWork.getId(),flowWork.getFlowWorkStatus(),workloads.size());
            }
        }
        if (workloads.size() == 1){
            // 获取关联工作量信息
            NepuWorkload mainWorkload = workloads.get(0);
            vo.setHasWorkload(true);
            vo.setWorkload(mainWorkload.getWorkload());
            vo.setUsedWorkload(mainWorkload.getUsedWorkload());
            vo.setWorkloadLock(mainWorkload.getWorkloadLock());
        }
        else if (workloads.size() == 0){
            // 获取关联工作量信息
            //NepuWorkload mainWorkload = workloads.get(0);
            vo.setHasWorkload(false);
            vo.setWorkload(0.0);
            vo.setUsedWorkload(0.0);
            vo.setWorkloadLock(0);
        }

        return new AsyncResult<>(vo);
    }

    @Override
    @Async("threadExecutor")
    public Future<List<WorkloadExportVO>> UserWorkloadAnalysisV2(UserBaseVO baseVO,String deptName
    ,String postType,String postGrade,String postLevel) {
        //根据 userId , 工作量类型--科研
        // 构建 Example
        NepuWorkload t = new NepuWorkload();
        t.setUserId(baseVO.getId());
        t.setWorkloadType(WorkloadTypeConst.RESEARCH);
        Example<NepuWorkload> example = Example.of(t);
        List<NepuWorkload> workloads = getExampleWorkloads(example);
        log.info("{}有{}条工作量记录",baseVO.getNickName(),workloads.size());
        // 根据 workloads 进行分析 申报类型，项目类型，
        // 新建返回数据列表
        List<WorkloadExportVO> list = new ArrayList<>();
        workloads.forEach(ele->{
            WorkloadExportVO vo = new WorkloadExportVO();
            // 写入基础信息
            BeanUtil.copyProperties(baseVO,vo, CopyOptions.create().setIgnoreError(true).setIgnoreNullValue(true));
            vo.setDeptName(deptName);
            // 查询工作量附加信息
            ResearchAttach attach = JsonUtil.string2Obj(ele.getWorkloadAttach(),ResearchAttach.class);
            assert attach != null;
            // 赋值 申报类型
            vo.setServiceType(attach.getResearchType());
            // 赋值 项目类型
            vo.setProjectType(attach.getDictName());
            // 赋值 项目名称
            vo.setProjectName(attach.getResearchName());
            //接受岗位类型参数（没绑定则跳过）
            if (baseVO.getPostId()!=null) {
                vo.setPostType(postType);
                vo.setPostGrade(postLevel+":"+postGrade);
            }else {
                vo.setPostType("未绑定岗位");
                vo.setPostGrade("未绑定岗位");
            }
            //赋值 是否是负责人
            if (ele.getWorkloadSource().equals(WorkloadSourceConst.APPLY)){
                vo.setWorkloadSource("是");
            }else {
                vo.setWorkloadSource("否");
            }
            Optional<NepuCycle> cycleOp = nepuCycleService.getById(ele.getCycleId());
            if (!cycleOp.isPresent()){
                vo.setCycle("周期不存在！");
            }else {
                vo.setCycle(cycleOp.get().getCycleName());
            }
            // 赋值 项目号 Query
            vo.setProjectCode(researchServiceCtl.getProjectCode(ele.getLinkId(),attach.getResearchType()));
            // 赋值 工作量
            vo.setWorkload(ele.getWorkload());
            // 赋值 工作量级别
            vo.setWorkloadLevel(ele.getWorkloadLevel());
            // 新增
            list.add(vo);
        });
        return new AsyncResult<>(list);
    }

    @Override
    public FinalWorkloadExportVO performanceAnalysis(UserBaseVO baseVO, String deptName, String postType, String postGrade, String postLevel,Double targetT,Double targetR,Double standard) {

        FinalWorkloadExportVO vo = new FinalWorkloadExportVO();
        //任务一 写入用户基础信息
        CompletableFuture<FinalWorkloadExportVO> infoFuture = CompletableFuture.supplyAsync(() -> {
            // 写入基础信息
            BeanUtil.copyProperties(baseVO,vo, CopyOptions.create().setIgnoreError(true).setIgnoreNullValue(true));
            vo.setDeptName(deptName);
            //接受岗位类型参数（没绑定则跳过）
            if (baseVO.getPostId()!=null) {
                vo.setPostType(postType);
                vo.setPostGrade(postLevel+":"+postGrade);
                vo.setTotalTeachW(targetT);
                vo.setTotalResearchW(targetR);
            }else {
                vo.setPostType("未绑定岗位");
                vo.setPostGrade("未绑定岗位");
            }
            return vo;
        });


        if (targetR==null||targetT==null){
            return vo;
        }
        if (targetR==0||targetT==0){
            return vo;
        }

        //任务二  查询教师的所有工作量
        NepuWorkload t = new NepuWorkload();
        t.setUserId(baseVO.getId());
        t.setCycleId(nepuCycleService.getNowResearchCycleId());
        System.out.println("周期id"+t.getCycleId());
        CompletableFuture<List<NepuWorkload>> NepuWorkloadC = CompletableFuture.supplyAsync(() -> {
            Example<NepuWorkload> example = Example.of(t);
            List<NepuWorkload> workloads = getExampleWorkloads(example);
            log.info("{}有{}条工作量记录",baseVO.getNickName(),workloads.size());
            return workloads;
        });
        //任务三 写入教学和科研分类得分，以及剩余的科研分(依赖任务二的执行结果)
//        vo.setTeachWorkload(0.0);
//        vo.setResearchA(0.0);
//        vo.setRemainderA(0.0);
//        vo.setResearchB(0.0);
//        vo.setRemainderB(0.0);
//        vo.setResearchC(0.0);
//        vo.setRemainderC(0.0);
//        CompletableFuture saleAttrFuture = NepuWorkloadC.thenAcceptAsync( workloads-> {
//            workloads.forEach(ele->{
//                double sum = 0.0;
//                if (ele.getWorkloadType().equals(WorkloadTypeConst.TEACH)){
//                    vo.setTeachWorkload(ele.getWorkload()+vo.getTeachWorkload());
//                }else if (ele.getWorkloadType().equals(WorkloadTypeConst.RESEARCH)){
//                    if(ele.getWorkloadSource().equals(WorkloadSourceConst.APPLY)&&ele.getUsedWorkload()!=0){
//                        WorkloadUseLog workloadUseLog = new WorkloadUseLog();
//                        workloadUseLog.setWorkloadId(ele.getId());
//                        Example<WorkloadUseLog> example = Example.of(workloadUseLog);
//                        List<WorkloadUseLog> workloadUseLogs = logService.findByExample(example);
//                        for (WorkloadUseLog useLog : workloadUseLogs) {
//                            sum += useLog.getWorkload();
//                        }
//                    }
//                    String level = ele.getWorkloadLevel().substring(0,1);
//                    switch (level)
//                    {
//                        case "A":
//                            vo.setResearchA(ele.getWorkload()+vo.getResearchA()-ele.getUsedWorkload()+sum);
//                            vo.setRemainderA(ele.getWorkload()-ele.getUsedWorkload()+vo.getRemainderA());
//                            break;
//                        case "B":
//                            vo.setResearchB(ele.getWorkload()+vo.getResearchB()-ele.getUsedWorkload()+sum);
//                            vo.setRemainderB(ele.getWorkload()-ele.getUsedWorkload()+vo.getRemainderB());
//                            break;
//                        case "C":
//                            vo.setResearchC(ele.getWorkload()+vo.getResearchC()-ele.getUsedWorkload()+sum);
//                            vo.setRemainderC(ele.getWorkload()-ele.getUsedWorkload()+vo.getRemainderC());
//                            break;
//                        default:
//                            log.info("级别错误！");
//                    }
//                }
//
//            });
//        });

        //任务三  写入教学得分
        vo.setTeachWorkload(0.0);
        CompletableFuture teachAttrFuture = NepuWorkloadC.thenAcceptAsync( workloads-> {
            workloads.forEach(ele->{
                if (ele.getWorkloadType().equals(WorkloadTypeConst.TEACH))
                    vo.setTeachWorkload(ele.getWorkload()+vo.getTeachWorkload());
             });
        });
        //任务四  写入科研分类得分和剩余科研分类得分
        vo.setResearchA(0.0);
        vo.setRemainderA(0.0);
        vo.setResearchB(0.0);
        vo.setRemainderB(0.0);
        vo.setResearchC(0.0);
        vo.setRemainderC(0.0);
        CompletableFuture researchAttrFuture = NepuWorkloadC.thenAcceptAsync( workloads-> {
            workloads.forEach(ele->{
                double sum = 0.0;
                if (ele.getWorkloadType().equals(WorkloadTypeConst.RESEARCH)){
                    if(ele.getUsedWorkload()!=0){
                        WorkloadUseLog workloadUseLog = new WorkloadUseLog();
                        workloadUseLog.setWorkloadId(ele.getId());
                        Example<WorkloadUseLog> example = Example.of(workloadUseLog);
                        List<WorkloadUseLog> workloadUseLogs = logService.findByExample(example);
                        for (WorkloadUseLog useLog : workloadUseLogs) {
                            sum += useLog.getWorkload();
                        }
                    }
                    String level = ele.getWorkloadLevel().substring(0,1);
                    switch (level)
                    {
                        case "A":
                            vo.setResearchA(ele.getWorkload()+vo.getResearchA()-ele.getUsedWorkload()+sum);
                            vo.setRemainderA(ele.getWorkload()-ele.getUsedWorkload()+vo.getRemainderA());
                            break;
                        case "B":
                            vo.setResearchB(ele.getWorkload()+vo.getResearchB()-ele.getUsedWorkload()+sum);
                            vo.setRemainderB(ele.getWorkload()-ele.getUsedWorkload()+vo.getRemainderB());
                            break;
                        case "C":
                            vo.setResearchC(ele.getWorkload()+vo.getResearchC()-ele.getUsedWorkload()+sum);
                            vo.setRemainderC(ele.getWorkload()-ele.getUsedWorkload()+vo.getRemainderC());
                            break;
                        default:
                            log.info("级别错误！");
                    }
                }

            });
        });

            //任务五 查找抵扣结果
        WorkloadUseLog workloadUseLog = new WorkloadUseLog();
        workloadUseLog.setUserId(baseVO.getId());
        workloadUseLog.setCycleId(nepuCycleService.getNowResearchCycleId());
        CompletableFuture<List<WorkloadUseLog>> WorkloadUseLogC = CompletableFuture.supplyAsync(() -> {
            Example<WorkloadUseLog> example = Example.of(workloadUseLog);
            List<WorkloadUseLog> workloadUseLogs = logService.findByExample(example);
            return workloadUseLogs;
        });
        //任务六 写入档内教学科研得分，超额教学工作量，其他工作量剩余，以及总绩效
        vo.setGradeTeach(0.0);
        vo.setGradeResearch(0.0);
        vo.setTeachBeyond(0.0);
        vo.setRemainderOther(0.0);
        vo.setTotal(0.0);
        CompletableFuture<Void> future = WorkloadUseLogC.thenAcceptAsync( workloadUseLogs-> {
            if (workloadUseLogs.size()!=0) {
                workloadUseLogs.forEach(ele -> {

                    if (ele.getUseMethod().equals(UseMethodConst.DEDUCT_TEACH)) {
                        vo.setGradeTeach(vo.getGradeTeach() + ele.getWorkload());
                    } else if (ele.getUseMethod().equals(UseMethodConst.DEDUCT_RESEARCH)) {
                        vo.setGradeResearch(vo.getGradeResearch() + ele.getWorkload());
                    } else if (ele.getUseMethod().equals(UseMethodConst.CONVERT_SALARY)) {
                        vo.setTeachBeyond(vo.getTeachBeyond() + ele.getWorkload());
                        vo.setTotal(vo.getTotal() + ele.getWorkload() * 40);
                    } else if (ele.getUseMethod().equals(UseMethodConst.MANAGE_SALARY)) {
                        vo.setRemainderOther(vo.getRemainderOther() + ele.getWorkload());
                        vo.setTotal(vo.getTotal() + ele.getWorkload() * 40);
                    } else {
                        log.info("工作量使用类型错误！");
                    }
                });
            }
        });

//        try {
//            CompletableFuture.allOf(infoFuture,NepuWorkloadC,saleAttrFuture,WorkloadUseLogC,future).get() ;
//        } catch (InterruptedException e) {
//            log.error("导出任务异步编排错误: ");
//            log.error(e.getMessage() );
//        } catch (ExecutionException e) {
//            log.error(e.getMessage() );
//        }
        CompletableFuture<Void> all = CompletableFuture.allOf(infoFuture,NepuWorkloadC,teachAttrFuture,researchAttrFuture,WorkloadUseLogC,future);
        all.join();
        if (vo.getPostGrade().equals("未绑定岗位")||vo.getPostType()==null){
            return vo;
        }
        if (vo.getGradeResearch()+vo.getGradeTeach()==(targetR+targetT)){
            vo.setTotal(standard*10000+vo.getTotal());
        }else {
            vo.setTotal((standard*10000*(vo.getGradeResearch()+vo.getGradeTeach())/(targetR+targetT))
                    +vo.getTotal());
        }
        System.out.println(vo);
        return vo;
    }

    @Override
    @Async("threadExecutor")
    public Future<List<TeachWorkloadExportVO>> UserTeachWorkload(UserBaseVO baseVO, String deptName
            , String postType, String postGrade, String postLevel) {
        //根据 userId , 工作量类型--科研
        // 构建 Example
        NepuWorkload t = new NepuWorkload();
        t.setUserId(baseVO.getId());
        t.setWorkloadType(WorkloadTypeConst.TEACH);
        Example<NepuWorkload> example = Example.of(t);
        List<NepuWorkload> workloads = getExampleWorkloads(example);
        log.info("{}有{}条教学工作量记录",baseVO.getNickName(),workloads.size());
        // 根据 workloads 进行分析 申报类型，项目类型，
        // 新建返回数据列表
        List<TeachWorkloadExportVO> list = new ArrayList<>();
        workloads.forEach(ele->{
            TeachWorkloadExportVO vo = new TeachWorkloadExportVO();
            // 写入基础信息
            BeanUtil.copyProperties(baseVO,vo, CopyOptions.create().setIgnoreError(true).setIgnoreNullValue(true));
            vo.setDeptName(deptName);
            // 赋值 教学周期
            vo.setCycleName(nepuCycleService.getCycleNameById(ele.getCycleId()));
            //接受岗位类型参数（没绑定则跳过）
            if (baseVO.getPostId()!=null) {
                vo.setPostType(postType);
                vo.setPostGrade(postLevel+":"+postGrade);
            }else {
                vo.setPostType("未绑定岗位");
                vo.setPostGrade("未绑定岗位");
            }
            // 赋值 工作量
            vo.setWorkload(ele.getWorkload());
            // 新增
            list.add(vo);
        });
        return new AsyncResult<>(list);
    }

    @Override
    @Async("threadExecutor")
    public Future<List<TypeExportVO>> WorkloadType(UserBaseVO baseVO, String deptName, String postType, String postGrade, String postLevel) {
        //根据 userId , 工作量类型--科研
        // 构建 Example
        NepuWorkload t = new NepuWorkload();
        t.setUserId(baseVO.getId());
        t.setWorkloadType(WorkloadTypeConst.RESEARCH);
        Example<NepuWorkload> example = Example.of(t);
        List<NepuWorkload> workloads = getExampleWorkloads(example);
//        log.info("{}有{}条工作量记录",baseVO.getNickName(),workloads.size());
        // 新建返回数据列表
        List<TypeExportVO> list = new ArrayList<>();
        //计算各级别分数
        double gradeA = 0;
        double gradeB = 0;
        double gradeC = 0;

        for (NepuWorkload workload : workloads) {
            String level = workload.getWorkloadLevel().substring(0,1);
            switch (level)
            {
                case "A":
                    gradeA=gradeA+workload.getWorkload()-workload.getUsedWorkload();
                    break;
                case "B":
                    gradeB=gradeB+workload.getWorkload()-workload.getUsedWorkload();
                    break;
                case "C":
                    gradeC=gradeC+workload.getWorkload()-workload.getUsedWorkload();
                    break;
                default:
                    log.info("级别错误！");
            }
        }
        log.info("{}的A类分:{}+B类分:{}+C类分:{}",baseVO.getNickName(),gradeA,gradeB,gradeC);
        TypeExportVO vo = new TypeExportVO();
        // 写入基础信息
        BeanUtil.copyProperties(baseVO,vo, CopyOptions.create().setIgnoreError(true).setIgnoreNullValue(true));
        vo.setDeptName(deptName);
        //接受岗位类型参数（没绑定则跳过）
        if (baseVO.getPostId()!=null) {
            vo.setPostType(postType);
            vo.setPostGrade(postLevel+":"+postGrade);
        }else {
            vo.setPostType("未绑定岗位");
            vo.setPostGrade("未绑定岗位");
        }
        vo.setGradeA(gradeA);
        vo.setGradeB(gradeB);
        vo.setGradeC(gradeC);
        list.add(vo);
        return new AsyncResult<>(list);
    }

    @Override
    @Async("threadExecutor")
    public Future<List<TypeExportXVO>> WorkloadTypeX(UserBaseVO baseVO, String deptName, String postType, String postGrade, String postLevel) {
        //1.查询本用户所有的工作量
        NepuWorkload t = new NepuWorkload();
        t.setUserId(baseVO.getId());
        t.setWorkloadType(WorkloadTypeConst.RESEARCH);
        Example<NepuWorkload> example = Example.of(t);
        List<NepuWorkload> workloads = getExampleWorkloads(example);
        List<TypeExportXVO> list = new ArrayList<>();
        //计算各级别分数
        double gradeA = 0;
        double gradeB = 0;
        double gradeC = 0;

        double usedA = 0;
        double usedB = 0;
        double usedC = 0;

        for (NepuWorkload workload : workloads) {
            String level = workload.getWorkloadLevel().substring(0,1);
            switch (level)
            {
                case "A":
                    gradeA=gradeA+workload.getWorkload();
                    usedA=usedA+workload.getUsedWorkload();
                    break;
                case "B":
                    gradeB=gradeB+workload.getWorkload();
                    usedB=usedB+workload.getUsedWorkload();
                    break;
                case "C":
                    gradeC=gradeC+workload.getWorkload();
                    usedC=usedC+workload.getUsedWorkload();
                    break;
                default:
                    log.info("级别错误！");
            }
        }
        //2.查询上一周期工作量
        NepuWorkload nepuWorkload = new NepuWorkload();
        nepuWorkload.setUserId(baseVO.getId());
        nepuWorkload.setParentId(nepuCycleService.getPreviousResearchCycle().getId());
        nepuWorkload.setWorkloadType(WorkloadTypeConst.RESEARCH);
        Example<NepuWorkload> example1 = Example.of(nepuWorkload);
        List<NepuWorkload> workload1 = getExampleWorkloads(example1);

        double residueA = 0;
        double residueB = 0;
        double residueC = 0;

        for (NepuWorkload workload : workload1) {
            String level = workload.getWorkloadLevel().substring(0,1);
            switch (level)
            {
                case "A":
                    residueA=residueA+workload.getWorkload()-workload.getUsedWorkload();
                    break;
                case "B":
                    residueB=residueB+workload.getWorkload()-workload.getUsedWorkload();
                    break;
                case "C":
                    residueC=residueC+workload.getWorkload()-workload.getUsedWorkload();
                    break;
                default:
                    log.info("级别错误！");
            }
        }

        //3.查询本年度工作量
        NepuWorkload nepuWorkload2 = new NepuWorkload();
        nepuWorkload2.setUserId(baseVO.getId());
        nepuWorkload2.setParentId(nepuCycleService.getNowResearchCycle().getId());
        nepuWorkload2.setWorkloadType(WorkloadTypeConst.RESEARCH);
        Example<NepuWorkload> example2 = Example.of(nepuWorkload2);
        List<NepuWorkload> workload2 = getExampleWorkloads(example2);
        double newA = 0;
        double newB = 0;
        double newC = 0;

        for (NepuWorkload workload : workload2) {
            String level = workload.getWorkloadLevel().substring(0,1);
            switch (level)
            {
                case "A":
                    newA=newA+workload.getWorkload();
                    break;
                case "B":
                    newB=newB+workload.getWorkload();
                    break;
                case "C":
                    newC=newC+workload.getWorkload();
                    break;
                default:
                    log.info("级别错误！");
            }
        }


        TypeExportXVO vo = new TypeExportXVO();
        // 写入基础信息
        BeanUtil.copyProperties(baseVO,vo, CopyOptions.create().setIgnoreError(true).setIgnoreNullValue(true));
        vo.setDeptName(deptName);
        //接受岗位类型参数（没绑定则跳过）
        if (baseVO.getPostId()!=null) {
            vo.setPostType(postType);
            vo.setPostGrade(postLevel+":"+postGrade);
        }else {
            vo.setPostType("未绑定岗位");
            vo.setPostGrade("未绑定岗位");
        }
        vo.setGradeA(gradeA);
        vo.setGradeB(gradeB);
        vo.setGradeC(gradeC);
        vo.setUsedA(usedA);
        vo.setUsedB(usedB);
        vo.setUsedC(usedC);
        vo.setResidueA(residueA);
        vo.setResidueB(residueB);
        vo.setResidueC(residueC);
        vo.setNewA(newA);
        vo.setNewB(newB);
        vo.setNewC(newC);
        System.out.println("vo:"+vo);
        list.add(vo);
        return new AsyncResult<>(list);
    }

    @Override
    public List<TopicExportVO> topicData() {
        List<TopicExportVO> list = new ArrayList<>();
        List<FlowWork> flowWorks = flowWorkService.findKycCheck("纵向课题审核-科研处","已结束");
        for (FlowWork flowWork : flowWorks) {
            TopicExportVO topicExportVO = new TopicExportVO();
            // 1.异步写入人员信息
            CompletableFuture<Void> userInfo = CompletableFuture.runAsync(() -> {
                Optional<SysUser> sysUserOp = userService.getById(Long.parseLong(flowWork.getInitiator()));
                if (sysUserOp.isPresent()){
                    topicExportVO.setNickName(sysUserOp.get().getNickName());
                    topicExportVO.setUserName(sysUserOp.get().getUserName());
                    Optional<SysDept> sysDeptOp = sysDeptService.getById(sysUserOp.get().getDeptId());
                    if (sysDeptOp.isPresent()){
                        topicExportVO.setDeptName(sysDeptOp.get().getDeptName());
                    }else {
                        topicExportVO.setDeptName("未绑定部门！");
                    }
                }else {
                    topicExportVO.setNickName("用户信息不存在！");
                    topicExportVO.setUserName("用户信息不存在！");
                }
            });

            // 3.异步写入纵向相关信息
            CompletableFuture<Void> topicInfo = CompletableFuture.runAsync(() -> {
                // 写入流程信息
                BeanUtil.copyProperties(flowWork,topicExportVO,CopyOptions.create().setIgnoreNullValue(true).setIgnoreError(true));
                Optional<NepuTopic> nepuTopicOp = nepuTopicService.getById(flowWork.getServiceId());
                if (nepuTopicOp.isPresent()){
                    topicExportVO.setTopicCode(nepuTopicOp.get().getTopicCode());
                }else {
                    topicExportVO.setTopicCode("信息不存在!");
                }
            });
            // 4.异步写入工作量相关信息
            CompletableFuture<Void> workloadInfo = CompletableFuture.runAsync(() -> {
                Optional<NepuWorkload> workloadOp = nepuWorkloadDAO.getOldWorkload(flowWork.getServiceId(),WorkloadSourceConst.APPLY);
                if (workloadOp.isPresent()){
                    topicExportVO.setLevel(workloadOp.get().getWorkloadLevel());
                    topicExportVO.setScore(String.valueOf(workloadOp.get().getWorkload()));
                }else {
                    topicExportVO.setLevel("工作量信息不存在!");
                    topicExportVO.setScore("工作量信息不存在!");
                }
            });
            CompletableFuture<Void> all = CompletableFuture.allOf(userInfo,topicInfo,workloadInfo);
            all.join();
            list.add(topicExportVO);

        }

        return list;
    }

    @Override
    @Async("threadExecutor")
    public Future<AnalysisUserWorkloadDTO> AnalysisUserWorkload(Long userId) {

//        log.info("开始分析{}",userId);
        double totalWorkload = 0.0;

        double totalUsedWorkload = 0.0;

        double totalResearchWorkload = 0.0;

        double levelAWorkload = 0.0;

        double levelBWorkload = 0.0;

        double levelCWorkload = 0.0;

        double totalTeachWorkload = 0.0;

        double totalManagementWorkload = 0.0;

        double totalPartTimeWorkload = 0.0;

        List<NepuWorkload> workloads = nepuWorkloadDAO.findByUserId(userId);

        for (NepuWorkload ele:workloads){
            // 总工作量
            totalWorkload = totalWorkload + ele.getWorkload();
            // 总使用工作量
            totalUsedWorkload = totalUsedWorkload + ele.getUsedWorkload();
            // 获取工作量类型
            String workloadType = ele.getWorkloadType();
            if (workloadType.equals(WorkloadTypeConst.RESEARCH)){
                totalResearchWorkload = totalResearchWorkload + ele.getWorkload();
                String workloadLevel = ele.getWorkloadLevel();
                if (workloadLevel.startsWith("A")){
                    levelAWorkload = levelAWorkload + ele.getWorkload();
                }else if (workloadLevel.startsWith("B")){
                    levelBWorkload = levelBWorkload + ele.getWorkload();
                }else if (workloadLevel.startsWith("C")){
                    levelCWorkload = levelCWorkload + ele.getWorkload();
                }
            }
            else if (workloadType.equals(WorkloadTypeConst.TEACH)){
                totalTeachWorkload = totalTeachWorkload + ele.getWorkload();
            }
            else if (workloadType.equals(WorkloadTypeConst.MANAGEMENT)){
                totalManagementWorkload = totalManagementWorkload + ele.getWorkload();
            }
            else if (workloadType.equals(WorkloadTypeConst.PART_TIME)){
                totalPartTimeWorkload = totalPartTimeWorkload + ele.getWorkload();
            }

        }
        AnalysisUserWorkloadDTO dto = new AnalysisUserWorkloadDTO();
        dto.setTotalWorkload(totalWorkload);
        dto.setTotalUsedWorkload(totalUsedWorkload);
        dto.setLevelAWorkload(levelAWorkload);
        dto.setLevelBWorkload(levelBWorkload);
        dto.setLevelCWorkload(levelCWorkload);
        dto.setTotalResearchWorkload(totalResearchWorkload);
        dto.setTotalTeachWorkload(totalTeachWorkload);
        dto.setTotalManagementWorkload(totalManagementWorkload);
        dto.setTotalPartTimeWorkload(totalPartTimeWorkload);
        log.info("{}分析完成,总工作量{}",userId,totalWorkload);
        return new AsyncResult<>(dto);

    }



    @Override
    public List<NepuWorkload> getExampleWorkloads(Example<NepuWorkload> example) {
        return nepuWorkloadDAO.findAll(example);
    }

//    @Override
//    public List<NepuWorkload> findByUserIdAndWorkloadTypeAndUsedUpOrderByWorkloadAsc(Long userId, String workloadType, Integer usedUp) {
//        return nepuWorkloadDAO.findByUserIdAndWorkloadTypeAndUsedUpOrderByWorkloadAsc(userId,workloadType,usedUp);
//    }

    @Override
    public Integer countByLinkId(String linkId) {
        return nepuWorkloadDAO.countByLinkId(linkId);
    }

    @Override
    public Optional<NepuWorkload> getLinkEntity(String linkId) {
        return nepuWorkloadDAO.findByLinkIdAndWorkloadSource(linkId, WorkloadSourceConst.APPLY);
    }

    @Override
    public List<NepuWorkload> getLinkList(String linkId) {
        return nepuWorkloadDAO.findByLinkId(linkId);
    }

    @Override
    public List<NepuWorkload> findByLinkId(String linkId) {
        return nepuWorkloadDAO.findByLinkId(linkId);
    }

    @Override
    public void batchDelete(List<String> ids) {
        nepuWorkloadDAO.deleteByIdIn(ids);
    }

    @Override
    public List<NepuWorkload> findTeachAndOther(Long userId,Integer usedUp,String cycleId) {
        return nepuWorkloadDAO.getTeachAndOther(userId,usedUp,cycleId);
    }

    @Override
    public ResponseDTO saveList(List<NepuWorkload> list) {
        return ResponseDTO.succData(nepuWorkloadDAO.saveAll(list));
    }

    @Override
    public ResponseDTO distributeWorkload(DistributeDTO dto, NepuWorkload nepuWorkload) {
        Long loginId = StpUtil.getLoginIdAsLong();
        // 1. 获取用户岗位信息
        Optional<SysUser> userOp = userService.getById(loginId);
        if (!userOp.isPresent()) return ResponseDTO.wrap(ResponseCodeConst.NOT_FOUND,"无用户信息");
        SysUser user = userOp.get();
        String postId = user.getPostId();
        Optional<NepuPost> postOp = nepuPostService.getById(postId);
        if (!postOp.isPresent()) return ResponseDTO.wrap(ResponseCodeConst.NOT_FOUND,"绑定岗位信息不存在");
        NepuPost nepuPost = postOp.get();
        // 判断是否可分配
        if (!nepuWorkload.getWorkloadType().equals(WorkloadTypeConst.RESEARCH)){
            return ResponseDTO.wrap(ResponseCodeConst.FORBIDDEN,"非科研工作量无法分配");
        }
        if (nepuWorkload.getWorkloadLock() <= 1){
            return ResponseDTO.wrap(ResponseCodeConst.FORBIDDEN,"工作量已锁,无法分配,请联系管理员解锁");
        }
        Double workload = nepuWorkload.getWorkload();
        // 判断登录用户是否有权限进行分配
//        if (nepuResearchWorkload.getUserId() == null) {
//            if (!nepuPaperDAO.getById(nepuResearchWorkload.getMapperId()).getCorrespondingAuthorId().equals(loginId)) {
//                return ResponseDTO.wrap(ResponseCodeConst.FORBIDDEN, "请由通讯作者代分配！");
//            }
//
//        } else {
//
//        }
        log.info("登录用户:{},负责人:{}", loginId, nepuWorkload.getUserId());
        if (!nepuWorkload.getUserId().equals(loginId)) {
            return ResponseDTO.wrap(ResponseCodeConst.FORBIDDEN, "该用户无分配工作量权限!");
        }
        List<NepuWorkload> list = new ArrayList<>();
        Double distributeCount = 0.0;
        for (DistributeItem item : dto.getItems()) {
            System.out.println("开始分配");
            // 1. 不可以给自己分配工作量
            if (item.getUserId().equals(nepuWorkload.getUserId())){
                return ResponseDTO.wrap(ResponseCodeConst.FORBIDDEN,"不可以给自己分配工作量");
            }
            // 2. 工作量信息大部分相同
            NepuWorkload ele = new NepuWorkload();
            BeanUtil.copyProperties(nepuWorkload, ele, "id");
            // 3. 设置工作量获取人员ID
            ele.setUserId(item.getUserId());
            // 4. 设置工作量获取人员身份信息 -- 论文区分比较细致
//            if (ele.getResearchType().equals("论文")) {
//
//                Optional<Object> entityOp = researchServiceCtl.getById(ele.getMapperId(), ResearchTypeConst.PAPER);
//                if (!entityOp.isPresent()) return ResponseDTO.wrap(ResponseCodeConst.NOT_FOUND,"对应论文信息未找到");
//                NepuPaper paper = (NepuPaper) entityOp.get();
//                if (paper.getFirstAuthorId().equals(item.getUserId()))
//                    ele.setPlayRole("第一作者");
//                if (paper.getSecondAuthorId().equals(item.getUserId()))
//                    ele.setPlayRole("第二作者");
//
//
//            }
//            // 5. 非论文条件都设置为参与人员
//            ele.setPlayRole("参与人员");
            // 6. 设置工作量
            ele.setWorkload(item.getWorkload());
            // 7. 设置为不可分配 锁-降级
            ele.setWorkloadLock(1);
            // 设置工作量来源为负责人分配
            ele.setWorkloadSource(WorkloadSourceConst.LEADER);
            // 8. 设置使用量为 0
            ele.setUsedWorkload(0.0);
            // 9. 添加进写入列表中
            list.add(ele);
            distributeCount += item.getWorkload();
        }
        double able = nepuWorkload.getWorkload()/2;
        // @TODO 管理岗和高层人才只可以分配一半
        if (nepuPost.getPostType().equals(PostTypeConst.MANAGE)){
            double canDistribute = nepuWorkload.getWorkload() - nepuWorkload.getUsedWorkload();
            if ((able >= distributeCount) && (canDistribute >= distributeCount)){

            }else {
                return ResponseDTO.wrap(ResponseCodeConst.ERROR_PARAM, "分配工作量不满足要求");
            }

        }
        // @TODO 项目已经参与抵扣，只可以分配剩余工作量 抵扣后仍然可以分配
        if (distributeCount > (nepuWorkload.getWorkload() - nepuWorkload.getUsedWorkload())) {
            return ResponseDTO.wrap(ResponseCodeConst.ERROR_PARAM, "分配工作量超标");
        } else {
            // 10. 设置分配人员信息
            nepuWorkload.setUsedWorkload(distributeCount + nepuWorkload.getUsedWorkload());
            // 11. 配置为不可再分配 锁-降级
            nepuWorkload.setWorkloadLock(1);
            // 12. 是否用尽
            if (nepuWorkload.getUsedWorkload().equals(nepuWorkload.getWorkload())){
                nepuWorkload.setUsedUp(1);
            }

            list.add(nepuWorkload);
        }
        return saveList(list);
    }


//    @Override
//    public ResponseDTO getAccessWorkload(Long userId, Integer usedUp) {
//        return null;
//    }

    @Override
    public WorkloadCountVO buildWorkloadCount(String type, Long userId, Integer usedUp) {
        return null;
    }

    @Override
    public Optional<NepuWorkload> getAccessEntity(String id) {
        return Optional.empty();
    }

//    @Override
//    public List<NepuWorkload> findByUserIdAndWorkloadTypeAndUsedUpOrderByWorkloadLevelDesc(Long userId, String workloadType, Integer usedUp) {
//        return nepuWorkloadDAO.findByUserIdAndWorkloadTypeAndUsedUpOrderByWorkloadLevelDesc(userId,workloadType,usedUp);
//    }
//
//    @Override
//    public List<NepuWorkload> findByUserIdAndWorkloadTypeAndUsedUp(Long userId, String workloadType, Integer usedUp) {
//        return nepuWorkloadDAO.findByUserIdAndWorkloadTypeAndUsedUp(userId,workloadType,usedUp);
//    }
//
//    @Override
//    public List<NepuWorkload> findByUserIdAndWorkloadTypeAndUsedUpAndCycleId(Long userId, String workloadType, Integer usedUp, String cycleId) {
//        return nepuWorkloadDAO.findByUserIdAndWorkloadTypeAndUsedUpAndCycleId(userId,workloadType,usedUp,cycleId);
//    }

    @Override
    public Integer countByUserIdAndResearchTypeAndCycleId(Long userId, String researchType, String cycleId) {
        List<NepuWorkload> nepuWorkloadList = nepuWorkloadDAO.findByUserIdAndCycleId(userId, cycleId);
        Integer totalNumber = 0;
        for (NepuWorkload nepuWorkload : nepuWorkloadList) {
            JSONObject jsonObject = JSONObject.parseObject(nepuWorkload.getWorkloadAttach());
            if (jsonObject.getString("researchType").equals(ResearchTypeConst.PAPER)) {
                totalNumber++;
            }
        }

        return totalNumber;
    }

    @Override
    public List<NepuWorkload> getByUserIdAndResearchTypeAndCycleId(Long userId, String researchType, String cycleId) {
        List<NepuWorkload> nepuWorkloadList = nepuWorkloadDAO.findByUserIdAndCycleId(userId, cycleId);
        List<NepuWorkload> res = new ArrayList<>();
        for (NepuWorkload nepuWorkload : nepuWorkloadList) {
            JSONObject jsonObject = JSONObject.parseObject(nepuWorkload.getWorkloadAttach());
            if (jsonObject.getString("researchType").equals(ResearchTypeConst.PAPER)) {
                res.add(nepuWorkload);
            }
        }
        return res;
    }

    @Override
    public PageResultDTO<NepuWorkload> getAll(Pageable pageable, Example<NepuWorkload> example) {
        Page<NepuWorkload> page;
        //是否为空 --
        if(Validator.isEmpty(example)){
            page = nepuWorkloadDAO.findAll(pageable);
        }else {
            page = nepuWorkloadDAO.findAll(example,pageable);
        }
        List<NepuWorkload> list = page.getContent();
        PageResultDTO<NepuWorkload> pageResultDTO = new PageResultDTO<>();
        pageResultDTO.setContent(list);
        pageResultDTO.setSize(page.getSize());
        pageResultDTO.setTotalPages(page.getTotalPages());
        pageResultDTO.setNumber(page.getNumber());
        pageResultDTO.setTotalElements(page.getTotalElements());

        return pageResultDTO;
    }

    @Override
    public ResponseDTO deleteById(String id) {
        //判断数据是否存在
        Optional<NepuWorkload> workloadUseLogOp = nepuWorkloadDAO.findById(id);
        if(!workloadUseLogOp.isPresent()) return ResponseDTO.wrap(ResponseCodeConst.NOT_FOUND,"ID:["+id+"]对应数据不存在");
        nepuWorkloadDAO.deleteById(id);
        return ResponseDTO.succMsg("删除成功!");
    }

    @Override
    public Optional<NepuWorkload> getById(String id) {
        return nepuWorkloadDAO.findById(id);
    }

    @Override
    public NepuWorkload saveOne(NepuWorkload nepuWorkload) {
        if (Validator.isNotEmpty(nepuWorkload.getId())){
            throw new BusinessException(ResponseCodeConst.ERROR_PARAM);
        }
        return nepuWorkloadDAO.save(nepuWorkload);
    }

    @Override
    public NepuWorkload updateOne(NepuWorkload nepuWorkload) {
        if (Validator.isEmpty(nepuWorkload.getId())){
            throw new BusinessException(ResponseCodeConst.ERROR_PARAM);
        }
        return nepuWorkloadDAO.save(nepuWorkload);
    }
    @Override
    public void researchDeduction(Long userId,Double needWorkload) {
        // 获取所有可以用于抵扣的科研工作量记录
        List<NepuWorkload> workloadList = nepuWorkloadDAO.findByUserIdAndWorkloadTypeAndUsedUpOrderByWorkloadLevelDesc(userId,WorkloadTypeConst.RESEARCH,0);
        double workloadSum = 0.0;
        //创建日志数组暂存数据，最后统一保存
        List<WorkloadUseLog> workloadUseLogList = new ArrayList<>();
        for (NepuWorkload workload:workloadList){
            // 附加信息转化
            ResearchAttach attach = JsonUtil.string2Obj(workload.getWorkloadAttach(),ResearchAttach.class);
            if (workloadSum + (workload.getWorkload()-workload.getUsedWorkload()) > needWorkload){
                assert attach != null;
                WorkloadUseLog useLog = buildResearchUseLog(workload.getCycleId(), userId, needWorkload - workloadSum, workload.getId(), UseMethodConst.DEDUCT_RESEARCH, workload.getLinkId(), attach.getResearchName(), workload.getCreatedTime());
                workloadUseLogList.add(useLog);
                workload.setUsedWorkload(workload.getUsedWorkload() + needWorkload - workloadSum);
                updateOne(workload);
                workloadSum = needWorkload;

            }else {
                assert attach != null;
                WorkloadUseLog useLog = buildResearchUseLog(workload.getCycleId(), userId, workload.getWorkload()-workload.getUsedWorkload(), workload.getId(), UseMethodConst.DEDUCT_RESEARCH, workload.getLinkId(), attach.getResearchName(), workload.getCreatedTime());
                workloadUseLogList.add(useLog);
                workload.setUsedWorkload(workload.getWorkload());
                workload.setUsedUp(1);
                updateOne(workload);
                workloadSum += workload.getWorkload();

            }
            //循环出口
            if (workloadSum==needWorkload){
                break;
            }
        }
        //将日志数组批量写入
        logService.saveList(workloadUseLogList);
        System.out.println("科研工作量抵扣结束！");
    }

    @Override
    public void teachDeduction(Long userId,Double needWorkload) {
        // 获取所有可以用于抵扣的教学工作量记录
        List<NepuWorkload> workloadList = nepuWorkloadDAO.findByUserIdAndWorkloadTypeAndUsedUpOrderByWorkloadLevelDesc(userId,WorkloadTypeConst.TEACH,0);
        double workloadSum = 0.0;
        //创建日志数组暂存数据，最后统一保存
        List<WorkloadUseLog> workloadUseLogList = new ArrayList<>();
        for (NepuWorkload workload:workloadList){
            if (workloadSum + (workload.getWorkload()-workload.getUsedWorkload()) > needWorkload){
                WorkloadUseLog useLog = buildTeachUseLog(workload.getCycleId(), userId, needWorkload - workloadSum, workload.getId(), UseMethodConst.DEDUCT_TEACH, workload.getCreatedTime());
                workloadUseLogList.add(useLog);
                workload.setUsedWorkload(workload.getUsedWorkload() + (needWorkload-workloadSum));
                updateOne(workload);
                workloadSum = needWorkload;

            }else {
                WorkloadUseLog useLog = buildTeachUseLog(workload.getCycleId(), userId, workload.getWorkload()-workload.getUsedWorkload(), workload.getId(), UseMethodConst.DEDUCT_TEACH, workload.getCreatedTime());
                workloadUseLogList.add(useLog);
                workload.setUsedWorkload(workload.getWorkload());
                workload.setUsedUp(1);
                updateOne(workload);
                workloadSum += workload.getWorkload();

            }
            //循环出口
            if (workloadSum==needWorkload){
                break;
            }
        }
        //将日志数组批量写入
        logService.saveList(workloadUseLogList);
        System.out.println("教学工作量抵扣结束！");

    }

    WorkloadUseLog buildLog(NepuWorkload t,Double useWorkload, String useMethod){
        ResearchAttach attach = JsonUtil.string2Obj(t.getWorkloadAttach(),ResearchAttach.class);
        WorkloadUseLog useLog = new WorkloadUseLog();

        useLog.setUserId(t.getUserId());
        useLog.setWorkload(useWorkload);
        useLog.setWorkloadId(t.getId());
        //工作量类型
        String workloadType = t.getWorkloadType();

        if (workloadType.equals(WorkloadTypeConst.TEACH) || workloadType.equals(WorkloadTypeConst.TEACH_ADD)){
            useLog.setCycleId(t.getParentId());
        }else {
            useLog.setCycleId(t.getCycleId());
        }
        useLog.setWorkloadType(workloadType);
        useLog.setUseMethod(useMethod);
        useLog.setLinkId(t.getLinkId());
        assert attach != null;
        if ((Validator.isEmpty(attach) && workloadType.equals(WorkloadTypeConst.TEACH))||attach.getResearchName().equals(WorkloadTypeConst.TEACH_ADD)){
            useLog.setLinkName("教学工作量[含追加]");
        }else {
            useLog.setLinkName(attach.getResearchName());
        }

        useLog.setWorkloadDate(t.getCreatedTime());
        return useLog;

    }

    /**
     * 使用 buildLog 替换该方法
     * @param cycleId
     * @param userId
     * @param workload
     * @param workloadId
     * @param useMethod
     * @param linkId
     * @param linkName
     * @param workloadDate
     * @return
     */
    @Deprecated
    WorkloadUseLog buildResearchUseLog(String cycleId, Long userId, Double workload, String workloadId, String useMethod, String linkId, String linkName, Date workloadDate){
        WorkloadUseLog useLog = new WorkloadUseLog();
        useLog.setCycleId(cycleId);
        useLog.setUserId(userId);
        useLog.setWorkload(workload);
        useLog.setWorkloadId(workloadId);
        useLog.setWorkloadType(WorkloadTypeConst.RESEARCH);
        useLog.setUseMethod(useMethod);
        useLog.setLinkId(linkId);
        useLog.setLinkName(linkName);
        useLog.setWorkloadDate(workloadDate);
        return useLog;
    }

    /**
     * 使用 buildLog 替换该方法
     * @param cycleId
     * @param userId
     * @param workload
     * @param workloadId
     * @param useMethod
     * @param workloadDate
     * @return
     */
    @Deprecated
    WorkloadUseLog buildTeachUseLog(String cycleId,Long userId, Double workload,String workloadId, String useMethod,Date workloadDate){
        WorkloadUseLog useLog = new WorkloadUseLog();
        useLog.setCycleId(cycleId);
        useLog.setUserId(userId);
        useLog.setWorkload(workload);
        useLog.setWorkloadId(workloadId);
        useLog.setUseMethod(useMethod);
        useLog.setWorkloadType(WorkloadTypeConst.TEACH);
        useLog.setLinkName("教学工作量");
        useLog.setWorkloadDate(workloadDate);
        return useLog;
    }
}
